home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-25 | 36.9 KB | 811 lines | [TEXT/CCL ] |
- ; (c) Copyright 1990 by University of Massachusetts. All rights reserved.
- ; This software was conceived, designed, and written by Dan Suthers
- ; while supported by the National Science Foundation under grant number
- ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
- ; CA. Partial support was also received from the Office of Naval Research
- ; under a University Research Initiative Grant, contract N00014-86-K-0764.
- ; Mr. Suthers created this software under his own initiative while in an
- ; academic relationship with the University of Massachusetts. The above
- ; copyright notice was a condition placed by University lawyers on approval
- ; of distribution of this software by Apple Computer, and is not meant to
- ; imply that this software was created in an employment or "work for hire"
- ; relationship between the University and Mr. Suthers.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; File: Rule-Browser.lisp
- ; Author: Dan Suthers
- ; Created: 04-Nov-88 13:58:46
- ; Modified: 22-Jun-90 02:22:42 (Dan Suthers)
- ; Language: Common Lisp
- ; Package: RULE
- ;
- ; Description: Loads and saves rules; Graphs justification trees for rule
- ; traces.
- ;
- ; (c) Copyright 1988, by Daniel D. Suthers
- ; Department of Computer and Information Science
- ; University of Massachusetts
- ; Amherst, Massachusetts 01003
- ;
- ; This software was conceived, designed, and written by Dan Suthers
- ; while supported by the National Science Foundation under grant number
- ; MDR 8751362, and by a fellowship from Apple Computer, Inc., Cupertino,
- ; CA. Partial support was also received from the Office of Naval Research
- ; under a University Research Initiative Grant, contract N00014-86-K-0764.
- ; I wish to acknowledge the generous support of Beverly Woolf, who obtained
- ; the above grants and encouraged me to pursue my own research interests in
- ; her lab. This work would not have been possible without the resources and
- ; stimulating environment of the Computer and Information Science department.
- ;
- ; Permission to use, modify, and distribute this software is granted subject
- ; to the following restrictions and understandings:
- ; 1. The file header, including this notice, shall be retained, and may be
- ; extended to include documentation of modifications to the software.
- ; 2. This material is for nonprofit educational and research purposes only.
- ; Users are requested, but not required, to inform Mr. Suthers of any
- ; noteworthy uses of this software.
- ; 3. Mr. Suthers and the University of Massachusetts make no warrantee or
- ; representation that the operation of this software will be error free,
- ; and are under no obligation to provide any services.
- ; 4. Any user of such software agrees to indemnify and hold harmless Mr.
- ; Suthers and the University of Massachusetts from all claims arising
- ; out of the use or misuse of this software, or arising out of any
- ; accident, injury, or damage whatsoever, and from all costs, counsel
- ; fees, and liabilities incurred in or about any such claim, action, or
- ; proceeding brought thereon.
- ; 5. All materials and reports developed as a consequence of the use of
- ; this software shall duly acknowledge such use, in accordance with
- ; the usual standards of acknowledging credit in academic research.
- ;
- ; Status: Appears to be working.
- ;
- ; Changes:
- ; 26-Dec-88 Adjusting labels.
- ; 06-Apr-89 Trace indentation; updated for new :lisp and :asserted nodes.
- ; 07-Nov-89 Wrote menu-item-update for trace-rules item.
- ; 30-Jan-90 Updated for version 1.3.1.
- ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (in-package :RULE)
-
- (require :MISC)
- (require :Rule-Defs)
- ;;; take our chances on the others. Don't know if they are doing forward or back.
- (require :Grapher)
-
- (export '(
- *rule-trace-window*
- graph-support-tree
- ))
-
- (use-package :DNET)
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defconstant PREDEFINED-WARRANTS '(:and :seq :or :asserted :bind :lisp))
-
- (defparameter *MIN-GRAPH-NODE-WIDTH* 12) ; 12 = |unsupported|
- (defparameter *MAX-GRAPH-NODE-WIDTH* 25)
-
- (defun LABEL-STRING (object-to-print lower-bound upper-bound)
- ;; Returns string version of <object-to-print> which is within the
- ;; bounds, and truncated or centered as needed.
- (let* ((object-string (format nil "~S" object-to-print))
- (string-length (length object-string))
- (string-of-spaces
- " "))
- (declare (string object-string) (fixnum string-length))
- (cond
- ((> string-length upper-bound)
- (setq object-string (subseq object-string 0 upper-bound))
- (setf (subseq object-string (- upper-bound 3) upper-bound) "...")
- object-string)
- ((>= string-length lower-bound) object-string)
- (T
- (let ((half-the-difference (/ (- lower-bound string-length) 2)))
- (declare (float half-the-difference))
- (concatenate 'string
- (subseq string-of-spaces 0 (floor half-the-difference))
- object-string
- (subseq string-of-spaces 0 (ceiling half-the-difference))))))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defparameter *RULE-TRACE-WINDOW*
- (ccl:oneof ccl:*fred-window*
- :window-title "Rule Trace"
- :window-position (ccl:make-point 2 337)
- :window-size (ccl:make-point 635 140)
- :window-font '("monaco" 9)
- :window-type :document-with-zoom
- :close-box-p nil
- :scratch-p T))
- (ccl:ask *rule-trace-window* (ccl:window-hide))
-
- (defmacro RULE-TRACE (template &rest args)
- ;; Works like format, but prints to rule trace window, and updates position.
- `(progn
- (let ((trace-buffer (ccl:ask *rule-trace-window* (ccl:window-buffer))))
- ;; Write in the new trace (T means end of buffer)
- (ccl:buffer-insert trace-buffer (format nil ,template ,@args) T)
- ;; Move the window so the new material can be seen.
- (ccl:ask
- *rule-trace-window*
- (ccl:set-mark (ccl:window-start-mark)
- (ccl:buffer-line-start trace-buffer T -10))
- (ccl:window-update)))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defparameter *SUPPORT-TREE-MOUSE-METHODS*
- (append
- (list
-
- (cons
- "Show Supported Bound Claims"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gw gv))
- (let ((trj-struct
- (grapher:graph-node-object (sm:gets 'grapher:graph-node gn))))
- (if (trj-node-p trj-struct)
- (let ((*print-pretty* t)
- (claim (trj-node-claim trj-struct))
- (binding-sets (trj-node-bindings trj-struct)))
- (ccl:ask *rule-trace-window*
- (unless (ccl:window-shown-p) (ccl:window-show))
- (unless (= (ccl:window-layer) 1) (ccl:set-window-layer 1)))
- (cond
- ;; There are variables bound: substitute bindings and show.
- (binding-sets
- (rule-trace "~&---------- SUPPORTED BOUND CLAIMS at ~A:"
- (first (grapher:graph-node-label
- (sm:gets 'grapher:graph-node gn))))
- (dolist (binding-set binding-sets)
- (rule-trace "~%~A~% Bindings: ~S"
- (utils:indent-string
- (prin1-to-string
- (dnet:substitute-transitive-bindings binding-set
- claim))
- 2)
- binding-set)))
- ;; There are no bindings: just show the claim if supported.
- ((eq (trj-node-modality trj-struct) ':supported)
- (rule-trace "~&---------- SUPPORTED CLAIM AT ~A:~%~A"
- (first (grapher:graph-node-label
- (sm:gets 'grapher:graph-node gn)))
- (utils:indent-string (prin1-to-string claim) 2)))
- ;; It is unsupported.
- (t (rule-trace "~&---------- UNSUPPORTED CLAIM AT ~A:~%~A"
- (first (grapher:graph-node-label
- (sm:gets 'grapher:graph-node gn)))
- (utils:indent-string (prin1-to-string claim) 2)))))
- (progn
- (ccl:ed-beep)
- (wind:message-dialogue
- "I can only show the Claim of a TRJ Node, but you selected an Arc.")))))))
-
- (cons
- "Show Unbound Claim"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gw gv))
- (let ((trj-struct
- (grapher:graph-node-object (sm:gets 'grapher:graph-node gn))))
- (if (trj-node-p trj-struct)
- (let ((*print-pretty* t))
- (ccl:ask *rule-trace-window*
- (unless (ccl:window-shown-p) (ccl:window-show))
- (unless (= (ccl:window-layer) 1) (ccl:set-window-layer 1)))
- (rule-trace "~&---------- UNBOUND CLAIM at ~A:~%~A"
- (first (grapher:graph-node-label
- (sm:gets 'grapher:graph-node gn)))
- (utils:indent-string
- (prin1-to-string (trj-node-claim trj-struct))
- 2)))
- (progn
- (ccl:ed-beep)
- (wind:message-dialogue
- "I can only show the Claim of a TRJ Node, but you selected an Arc.")))))))
-
- (cons
- "Show Arc Bindings"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gw gv))
- (let ((trj-struct
- (grapher:graph-node-object (sm:gets 'grapher:graph-node gn))))
- (if (trj-arc-p trj-struct)
- (let ((*print-pretty* t))
- (ccl:ask *rule-trace-window*
- (unless (ccl:window-shown-p) (ccl:window-show))
- (unless (= (ccl:window-layer) 1) (ccl:set-window-layer 1)))
- (rule-trace "~&---------- ARC BINDINGS at ~A: ~S"
- (grapher:graph-node-label (sm:gets 'grapher:graph-node gn))
- (trj-arc-bindings trj-struct)))
- (progn
- (ccl:ed-beep)
- (wind:message-dialogue
- "I can only show the Bindings of a TRJ Arc, but you selected a Node.")))))))
-
- (cons
- "Make this Node the Root"
- (compile
- nil
- '(lambda (gw gv gn)
- (ccl:ask gw
- (let* ((gv-struct (sm:gets 'grapher:graph-view gv))
- (trj-struct (grapher:graph-node-object
- (sm:gets 'grapher:graph-node gn)))
- (new-gv
- (if (trj-node-p trj-struct)
- (trj-node->graph-view
- trj-struct
- (grapher:graph-view-style gv-struct)
- (grapher:graph-view-ordering gv-struct)
- (grapher:graph-view-depth-bound gv-struct)
- gv)))) ; parent view
- (when new-gv
- (grapher:set-graph-view new-gv)
- (ccl:set-window-title
- (label-string (trj-node-claim trj-struct) 10 40))
- (ccl:window-select)
- (ccl:view-draw-contents))
- (unless new-gv
- (ccl:ed-beep)
- (wind:message-dialogue
- "I can't make a TRJ Arc the Root; Please select a TRJ Node.")
- ;; The graph-view of gw was set to nil since we
- ;; thought gv was to be replaced ... restore it.
- (grapher:set-graph-view gv :layout nil)
- (ccl:view-draw-contents)))))))
-
- (cons
- "Backup Once to Parent View"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gn))
- (ccl:ask gw
- (let ((parent-view
- (grapher:graph-view-info-image :parent-view gv)))
- (if parent-view
- (if (sm:gets 'grapher:graph-view parent-view)
- (progn
- (grapher:set-graph-view parent-view :layout nil)
- (ccl:set-window-title
- (label-string
- (trj-node-claim
- (grapher:graph-view-info-image :original-root parent-view))
- 10 40))
- (ccl:window-select)
- (ccl:view-draw-contents)
- (unless (grapher:windows-using-graph-view gv)
- (grapher:dispose-graph-view gv)))
- (progn (ccl:ed-beep)
- (setf (grapher:graph-view-info-image :parent-view gv) nil)
- (wind:message-dialogue
- "The parent view appears to have been destroyed.")
- ;; The graph-view of gw was set to nil since we
- ;; thought gv was to be replaced ... restore it.
- (grapher:set-graph-view gv :layout nil)
- (ccl:view-draw-contents)))
- (progn (ccl:ed-beep)
- (wind:message-dialogue
- "This graph view has no parent view.")
- (grapher:set-graph-view gv :layout nil)
- (ccl:view-draw-contents))))))))
-
- (cons
- "Backup All the Way to Original View"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gn))
- (ccl:ask gw
- (let ((garbage-views nil) (original-view nil))
- ;; Search up to find original view; also recording the views
- ;; to be disposed of along the way.
- (do* ((parent-view
- (grapher:graph-view-info-image :parent-view gv)
- (grapher:graph-view-info-image :parent-view current-view))
- (current-view gv))
- ;; Invariant here: parent-view is parent of current-view,
- ;; so when parent-view nil, current-view is the root.
- ((null parent-view) (setq original-view current-view))
- (if (sm:gets 'grapher:graph-view parent-view)
- (progn
- (push current-view garbage-views)
- (setq current-view parent-view))
- (progn
- (ccl:ed-beep)
- (setf (grapher:graph-view-info-image :parent-view current-view) nil)
- (wind:message-dialogue
- "The parent of view ~A appears to have been destroyed."
- current-view)
- (setq parent-view nil)))) ; to exit
- (grapher:set-graph-view original-view :layout nil) ; already laid out
- (ccl:set-window-title
- (label-string
- (trj-node-claim
- (grapher:graph-view-info-image :original-root original-view))
- 10 40))
- (ccl:window-select)
- (ccl:view-draw-contents)
- (dolist (ggv garbage-views)
- (unless (grapher:windows-using-graph-view ggv)
- (grapher:dispose-graph-view ggv))))))))
-
- (cons
- "New Window with this Node as Root"
- (compile
- nil
- '(lambda (gw gv gn)
- (let* ((gv-struct (sm:gets 'grapher:graph-view gv))
- (trj-struct (grapher:graph-node-object
- (sm:gets 'grapher:graph-node gn)))
- (roots (list trj-struct))
- (style (grapher:graph-view-style gv-struct))
- (ordering (grapher:graph-view-ordering gv-struct))
- (depth-bound (grapher:graph-view-depth-bound gv-struct)))
- (when (trj-node-p trj-struct)
- (multiple-value-setq
- (roots style ordering depth-bound)
- (grapher:graph-view-parameter-dialogue
- (label-string (trj-node-claim trj-struct) 10 40)
- roots nil style ordering depth-bound))
- (ccl:oneof
- grapher:*graph-window*
- :window-title (label-string (trj-node-claim trj-struct) 10 40)
- :graph-view
- (trj-node->graph-view trj-struct style ordering depth-bound gv)))
- (unless (trj-node-p trj-struct)
- (ccl:ed-beep)
- (wind:message-dialogue
- "I can't make a TRJ Arc the Root; Please select a TRJ Node."))))))
-
- ;;; Put this back in when we add a mouse method for invoking the RBR to fill out
- ;;; a subtree.
- ;;; ("Update Graph View for Changes"
- ;;; . (lambda (gw gv gn)
- ;;; (declare (ignore gn))
- ;;; (let* ((gv-struct (sm:gets 'grapher:graph-view gv))
- ;;; (root (grapher:graph-view-info-image :original-root gv))
- ;;; (style (grapher:graph-view-style gv-struct))
- ;;; (ordering (grapher:graph-view-ordering gv-struct))
- ;;; (depth-bound (grapher:graph-view-depth-bound gv-struct))
- ;;; (parent-view (grapher:graph-view-info-image :parent-view gv))
- ;;; (new-view nil) (roots (list root)))
- ;;; (multiple-value-setq
- ;;; (roots style ordering depth-bound)
- ;;; (grapher:graph-view-parameter-dialogue
- ;;; root roots nil style ordering depth-bound))
- ;;; (ccl:ask gw
- ;;; (grapher:set-graph-view nil)
- ;;; (setq new-view
- ;;; (trj-node->graph-view
- ;;; root style ordering depth-bound parent-view))
- ;;; (unless (grapher:windows-using-graph-view gv)
- ;;; (grapher:dispose-graph-view gv))
- ;;; (grapher:set-graph-view new-view)
- ;;; (ccl:set-window-title
- ;;; @@@ need to define TRJ-STRUCT (label-string (trj-node-claim trj-struct) 10 40))
- ;;; (ccl:window-select)
- ;;; (ccl:view-draw-contents)))))
-
- (cons
- "Edit Associated Rule"
- (compile
- nil
- '(lambda (gw gv gn)
- (declare (ignore gw gv))
- (let ((trj-object
- (grapher:graph-node-object (sm:gets 'grapher:graph-node gn))))
- (if (trj-arc-p trj-object)
- (let ((warrant (trj-arc-warrant trj-object)))
- (cond ((member warrant predefined-warrants)
- (ccl:ed-beep)
- (wind:message-dialogue
- "This is an ~S arc, which does not reference a rule."
- warrant))
- ((and (symbolp warrant) (sm:gets 'rule warrant))
- (sm:edits 'rule warrant))
- (T
- (ccl:ed-beep)
- (wind:message-dialogue "Rule ~S does not exist!" warrant))))
- (progn
- (ccl:ed-beep)
- (wind:message-dialogue
- "You selected a TRJ Node, but rules are only referenced by TRJ Arcs!")))))))
-
- )
- ;; Note that SM stores unevaluated expressions producing defaults.
- (eval
- (cdr (assoc 'grapher::mouse-methods
- (sm:slot-defaults 'grapher:graph-view))))))
-
- (defun GRAPH-SUPPORT-TREE (root-node &key (style :vertical-tree)
- (ordering :as-found)
- (depth-bound 6)
- (window-size (ccl:make-point 635 280))
- (window-position
- (ccl:make-point 2 ccl:*menubar-bottom*))
- &aux (roots (list root-node)))
- "graph-support-tree <root-node> &key <style> <ordering> <depth-bound>
- <window-size> <window-position> [Function]
- Graphs the tree of support below <root-node>, after asking user for
- graph parameters."
- (check-type root-node trj-node)
- (check-type style keyword)
- (check-type ordering keyword)
- (check-type depth-bound fixnum)
-
- ;; Get desired parameters.
- (multiple-value-setq
- (roots style ordering depth-bound)
- (grapher:graph-view-parameter-dialogue
- (label-string (trj-node-claim root-node) 10 40)
- roots nil style ordering depth-bound))
-
- ;; Graph and put up in window. Exist method handles layout, selecting, and drawing.
- (ccl:oneof grapher:*graph-window*
- :window-title (label-string (trj-node-claim root-node) 10 40)
- :window-size window-size
- :window-position window-position
- :graph-view
- (TRJ-NODE->graph-view root-node style ordering depth-bound nil)))
-
- (defun TRJ-NODE->GRAPH-VIEW (root-node style ordering depth-bound parent-view)
- (declare (trj-node root-node) (symbol parent-view) (keyword style ordering)
- (fixnum depth-bound))
- (let ((graph-view-name
- (utils:unique-symbol (label-string (trj-node-claim root-node) 10 40))))
- (declare (symbol graph-view-name))
- (grapher:create-graph-view
- graph-view-name
- (list (graph-trj-node-subtree root-node depth-bound))
- depth-bound style ordering
- '("Geneva" 9) '("chicago" 12) 10
- `((:parent-view . ,parent-view) ; info
- (:original-root . ,root-node))
- *support-tree-mouse-methods*)))
-
- (defun GRAPH-TRJ-NODE-SUBTREE (root-node depth-left)
- ;; Constructs graphical tree of support, Returns top level graph node created.
- (declare (trj-node root-node) (fixnum depth-left)
- (optimize (safety 1) (space 2) (speed 3)))
-
- ;; Make a graph node labeled by claim and modality and branching
- ;; on support via graphed trj-arcs to reach other trj-nodes.
- (grapher:create-graph-node
- (gensym)
- ;; Labels. Center the modality in wide nodes.
- (let* ((claim-label (label-string (trj-node-claim root-node)
- *min-graph-node-width*
- *max-graph-node-width*))
- (claim-label-length (length claim-label)))
- (declare (string claim-label) (fixnum claim-label-length))
- (list claim-label
- (label-string (trj-node-modality root-node)
- (max *min-graph-node-width* claim-label-length)
- (min *max-graph-node-width* claim-label-length))))
-
- ;; Children
- (mapcan #'(lambda (ta)
- (declare (trj-arc ta))
- (graph-trj-arc-subtree ta (1- depth-left)))
- (trj-node-support root-node))
- ;; Box style a function of whether there is a subtree (even if not shown).
- (if (trj-node-support root-node) :round-frame :frame)
- ;; Connector; Object
- T root-node))
-
- (defun GRAPH-TRJ-ARC-SUBTREE (root-arc depth-left)
- ;; Constructs subtree below <root-arc>; Returns the graph node root for <root-arc>.
- (declare (trj-arc root-arc) (fixnum depth-left)
- (optimize (safety 1) (space 2) (speed 3)))
-
- (unless (= depth-left 0)
- (case (trj-arc-warrant root-arc)
- ((:asserted) (graph-trj-asserted-subtree root-arc))
- ((:bind) (graph-trj-bind-subtree root-arc))
- (otherwise
- (list
- (grapher:create-graph-node
- (gensym)
- ;; Label (could be :AND, :SEQ, :OR, or rule name, which may be long).
- (label-string (trj-arc-warrant root-arc) 1 *max-graph-node-width*)
- ;; Children
- (mapcar #'(lambda (tn)
- (declare (trj-node tn))
- (graph-trj-node-subtree tn depth-left)) ; only count node depth.
- (trj-arc-grounds root-arc))
- ;; Box style
- :none
- ;; Connector; Object
- nil root-arc))))))
-
- (defun GRAPH-TRJ-ASSERTED-SUBTREE (root-arc)
- (declare (trj-arc root-arc) (fixnum depth-left)
- (optimize (safety 1) (space 2) (speed 3)))
- (list
- (grapher:create-graph-node
- ;; Name, Label
- (gensym) "Asserted"
- ;; Children
- (list
- (grapher:create-graph-node
- (gensym)
- ;; Bogus frame needed since mouse methods assume list label.
- (list (label-string (trj-node-claim (first (trj-arc-grounds root-arc)))
- 1 *max-graph-node-width*))
- nil :frame T (first (trj-arc-grounds root-arc))))
- ;; Box-Style, Connector, Object.
- :none nil root-arc)))
-
- (defun GRAPH-TRJ-BIND-SUBTREE (root-arc)
- (declare (trj-arc root-arc) (fixnum depth-left)
- (optimize (safety 1) (space 2) (speed 3)))
- (list
- (grapher:create-graph-node
- ;; Name, Label, Children, Box-Style, Connector, Object.
- (gensym) "Bind" nil :rect T root-arc)))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defparameter *RULE-MENU*
- (let* ((line-item
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "-"))
-
- (graph-support-tree
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Graph Last Support Tree"
- :menu-item-action
- #'(lambda ()
- (if (and (boundp '*support-tree*) (trj-node-p *support-tree*))
- (graph-support-tree *support-tree*)
- (progn
- (ccl:ed-beep)
- (wind:message-dialogue
- "RULE:*SUPPORT-TREE* is not bound to a TRJ-NODE. Call RULE:SUPPORT first."))))))
-
- (graph-support-for
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Graph Support For ..."
- :menu-item-action
- #'(lambda ()
- (let ((goal
- (read-from-string
- (wind:get-string-dialogue
- "Graph support for what goal expression?")))
- (data-base
- (wind:menu-dialogue (sm:instances 'dnet:dnet)
- "Use what DNET for the Data Base?"))
- (rule-base
- (wind:menu-dialogue (sm:instances 'dnet:dnet)
- "Use what DNET for the Rule Base?"))
- (record-failure
- (wind:y-or-n-dialogue "Graph failed attempts to support?")))
- (ccl:eval-enqueue
- `(multiple-value-bind
- (success support-node)
- (support ',goal ',data-base ',rule-base
- :record-failure ',record-failure)
- (cond (success (graph-support-tree support-node))
- (',record-failure (graph-support-tree support-node))
- (t (ccl:ed-beep)
- (wind:message-dialogue "~S was not supported." ',goal)))))))))
- (trace-rules
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Trace Rules"
- :menu-item-action
- #'(lambda ()
- (if *rule-trace*
- (setf *rule-trace* nil)
- (setf *rule-trace* *rule-trace-window*))
- (if *rule-trace*
- (ccl:set-menu-item-check-mark t)
- (ccl:set-menu-item-check-mark nil)))))
-
- (show-rule-trace
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Show Rule Trace"
- :menu-item-action
- #'(lambda ()
- (ccl:ask *rule-trace-window*
- (unless (ccl:window-shown-p) (ccl:window-show))
- (ccl:window-select)))))
-
- (hide-rule-trace
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Hide Rule Trace"
- :menu-item-action
- #'(lambda () (ccl:ask *rule-trace-window*
- (when (ccl:window-shown-p) (ccl:window-hide))))))
-
- (reset-item
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Reset Rules ..."
- :menu-item-action
- #'(lambda ()
- (when (wind:y-or-n-dialogue
- "Destroy all in-memory instances of type RULE? (Rule base DNETs will still be usable; you just can't edit them any more.)")
- (ccl:eval-enqueue
- '(progn
- (sm:destroy-sm-editor-windows-of-type 'rule :ask-user T)
- (sm:reset-type 'rule)))))))
-
- ;; This is here mainly for consistency, since we have Save Rules here. But
- ;; the user could use Save Type.
- (load-item
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Load Rules ..."
- :menu-item-action
- #'(lambda ()
- (let ((file-path
- (ccl:choose-file-dialog
- :directory
- (format nil "~A~A.~A"
- sm:*default-instance-file-path*
- 'rule
- sm:*default-instance-file-type*))))
- (if (probe-file file-path)
- (progn
- ;; Change default path to one given, and record path
- (setf sm:*default-instance-file-path*
- (directory-namestring file-path))
- (ccl:eval-enqueue
- `(progn (sm:load-type 'rule :path ',file-path)
- (add-all-rules))))
- (wind:message-dialogue
- "File ~S doesn't seem to exist." (namestring file-path)))))))
-
- ;; We need a specialized Save Rules because we have to find all the variables
- ;; in the rules and define them, using save-type's :init-forms argument.
- ;; This code is modified from SMEDIT's Save Type menu item: see comments there.
- (save-item
- (ccl:oneof
- ccl:*menu-item*
- :menu-item-title "Save Rules ..."
- :menu-item-action
- #'(lambda ()
- (let* ((file-path
- (pathname
- (ccl:choose-new-file-dialog
- :directory
- (let ((prev-path (get 'rule 'sm::$SM-instance-path$)))
- (if prev-path
- (make-pathname
- :device (pathname-device prev-path)
- :directory (pathname-directory prev-path)
- :name (pathname-name prev-path)
- :type sm:*default-instance-file-type*)
- (make-pathname
- :directory sm:*default-instance-file-path*
- :name "RULE"
- :type sm:*default-instance-file-type*)))
- :prompt (format nil "Save RULEs to ..."))))
- (backup-path
- (make-pathname
- :host (pathname-host file-path)
- :device (pathname-device file-path)
- :directory (pathname-directory file-path)
- :name (pathname-name file-path)
- :type "bak"))
- (instances (sm:instances 'rule)))
- (multiple-value-bind
- (compile-p define-type-p specify-instances append-p)
- (sm:save-type-parameter-dialogue 'rule)
- (if specify-instances
- (setf instances
- (if (wind:y-or-n-dialogue
- "Are the rules you want to save interned in a particular Rule Base (DNET)?")
- (let ((rule-bases nil) (rule-base nil) (rules nil))
- (dolist (r (sm:instances 'rule))
- (dolist (rb (rule-interned-in (sm:gets 'rule r)))
- (pushnew rb rule-bases)))
- (setf rule-base
- (wind:menu-dialogue
- rule-bases
- "Save rules in which Rule Base?"))
- (dolist (r (sm:instances 'rule))
- (if (member rule-base (rule-interned-in (sm:gets 'rule r)))
- (push r rules)))
- rules)
- (wind:multiple-menu-dialogue
- instances
- "Choose the instances of RULE to save to ~S"
- (namestring file-path)))))
- (when (and (not append-p) (probe-file file-path))
- (if (probe-file backup-path) (delete-file backup-path))
- (rename-file file-path backup-path)
- (format T "~&;~A backed up to ~A"
- (namestring file-path) (namestring backup-path)))
- (setf sm:*default-instance-file-path*
- (directory-namestring file-path))
- ;; Find the variables and cons up declarations for them.
- (let ((variable-names
- (sort
- (mapcar
- #'symbol-name
- (delete-duplicates
- (reduce
- #'nconc
- (mapcar
- #'(lambda (r &aux (rstruct (sm:gets 'rule r)))
- (append
- (variables-in-pattern (rule-antecedent rstruct))
- (variables-in-pattern (rule-consequent rstruct))))
- instances))))
- #'string<)))
- (sm:save-type 'rule
- :path file-path
- :style :pretty-macro
- :compile nil
- :define-type define-type-p
- :instances instances
- :init-forms (list (cons 'defvariables variable-names))
- :append append-p)
- (format T "~&;Instances of RULEs saved to ~S"
- (namestring file-path))
- (if compile-p
- (ccl:eval-enqueue `(compile-file ,(namestring file-path))))
- (unless specify-instances
- (ccl:eval-enqueue
- '(sm:destroy-sm-editor-windows-of-type 'rule)))))))))
-
- (deinstall-item
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "Hide This Menu"
- :menu-item-action
- '(ccl:ask *rule-menu* (ccl:menu-deinstall))))
- (rule-menu (ccl:oneof ccl:*menu*
- :menu-title "RULES"
- :menu-items (list graph-support-tree
- graph-support-for
- line-item
- trace-rules
- show-rule-trace
- hide-rule-trace
- line-item
- load-item
- save-item
- reset-item
- line-item
- deinstall-item))))
- (ccl:defobfun (ccl:menu-item-update trace-rules) ()
- (if *rule-trace*
- (ccl:set-menu-item-check-mark t)
- (ccl:set-menu-item-check-mark nil)))
- (ccl:ask rule-menu (ccl:menu-install))
- (ccl:ask line-item (ccl:menu-item-disable))
- ;; Menu-dispose dumped from version 1.3.1?
- (if (and (boundp '*rule-menu*)
- (typep *rule-menu* ccl:*menu*))
- (ccl:ask *rule-menu* (ccl:menu-deinstall)))
- rule-menu))
-
- (ccl:ask ccl:*tools-menu*
- (ccl:add-menu-items
- (ccl:oneof ccl:*menu-item*
- :menu-item-title "Restore RULES Menu"
- :menu-item-action
- #'(lambda ()
- (ccl:ask *rule-menu*
- (unless (ccl:menu-installed-p) (ccl:menu-install)))))))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- (provide :Rule-Browser)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;;; the end.